﻿using System;
using System.Collections.Generic;

namespace Compiler
{
    /// <summary>
    /// 中间代码生成
    /// </summary>
    public static class IntermediateCodeGeneration
    {
        /// <summary>
        /// 符号栈
        /// </summary>
        public static Stack<string> mSymbolStack = new Stack<string>();
        /// <summary>
        /// 变量栈
        /// </summary>
        public static Stack<string> mArgumentStack = new Stack<string>();
        /// <summary>
        /// 临时变量下标
        /// </summary>
        public static int mT_id = 0;
        /// <summary>
        /// 中间代码生成接口
        /// </summary>
        public static void Generate(string type, Token token)
        {
            var op = type.Split(new char[] { '@', '_' }, StringSplitOptions.RemoveEmptyEntries);
            if(!Generator.GenerateQuaternion(op[0], token))
            {

            }
        }
        public static void Init()
        {
            Generator.mQuaternions = Quaternion.Quaternions;
            mSymbolStack.Clear();
            mArgumentStack.Clear();
            mT_id = 0;
        }
        /// <summary>
        /// 四元式生成器
        /// </summary>
        private static class Generator
        {
            public static List<Quaternion> mQuaternions;
            /// <summary>
            /// 一元的
            /// </summary>
            private static readonly List<string> strs1 = new List<string>("break continue".Split(' '));
            /// <summary>
            /// 二元的
            /// </summary>
            private static readonly List<string> strs2 = new List<string>("if FUN return".Split(' '));
            /// <summary>
            /// 生成四元式
            /// </summary>
            public static bool GenerateQuaternion(string action, Token token)
            {
                //变量入栈
                if (action == "PUSH")
                {
                    mArgumentStack.Push(token.Value);
                }
                //符号入栈
                if (action == "SAVE")
                {
                    mSymbolStack.Push(token.Value);
                }
                //生成四元式
                if (action == "GEQ")
                {
                    if (strs1.Contains(token.Value))
                    {
                        mQuaternions.Add(new Quaternion(token.Value, "_", "_", "_"));
                    }
                    else
                    {
                        string op;
                        try
                        {
                            op = mSymbolStack.Pop();
                            Compiler.Log(new Exception($" s= {op}"));
                        }
                        catch (Exception e)
                        {
                            Compiler.Log(e);
                            return false;
                        }
                        if (strs2.Contains(op))
                        {
                            string arg1;
                            try
                            {
                                arg1 = mArgumentStack.Pop();
                            }
                            catch (Exception e)
                            {
                                Compiler.Log(e);
                                return false;
                            }
                            mQuaternions.Add(new Quaternion(op, arg1, "_", "_"));
                        }
                        //三元的
                        else if (op == "=" || op == "callr")
                        {
                            try
                            {
                                var arg1 = mArgumentStack.Pop();
                                var result = mArgumentStack.Pop();
                                mQuaternions.Add(new Quaternion(op, arg1, "_", result));
                            }
                            catch (Exception e)
                            {
                                Compiler.Log(e);
                                return false;
                            }
                        }
                        //四元的
                        else
                        {
                            try
                            {
                                var arg2 = mArgumentStack.Pop();
                                var arg1 = mArgumentStack.Pop();
                                var result = $"T{mT_id++}";
                                mArgumentStack.Push(result);
                                mQuaternions.Add(new Quaternion(op, arg1, arg2, result));
                            }
                            catch (Exception e)
                            {
                                Compiler.Log(e);
                                return false;
                            }
                        }
                    }
                }
                return true;
            }
        }
    }
}
